package com.theaf.core.mq.service;


import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.SendResult;
import com.aliyun.openservices.ons.api.exception.ONSClientException;
import com.theaf.core.mq.message.Message;
import com.theaf.core.mq.properties.MqBaseProperties;
import com.theaf.core.mq.properties.ProducerProperties;
import com.theaf.core.utils.SerializationUtils;
import com.theaf.core.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Properties;

/**
 * @author luojuan
 * @create 2017-11-27 15:24
 */

public class ProducerServer {

    private static final Log logger = LogFactory
            .getLog(ProducerServer.class);

    private Producer producer;

    private static ProducerProperties producerProperties;

    private static MqBaseProperties mqBaseProperties;


    private ProducerServer(){
        logger.info("The aliyun message queue producer starts up.");
        Class propertiesClass =  producerProperties.getClass();
        Field[] fs = propertiesClass.getDeclaredFields();
        Properties properties = new Properties();
        Arrays.asList(fs).forEach(ele -> {
            ele.setAccessible(true);
            try {
                Object val = ele.get(producerProperties);
                properties.put( StringUtils.toUpperFristChar(ele.getName()) , val);
            } catch (IllegalAccessException e) {
                logger.info("The aliyun message queue producer startup failed:" + e.getMessage());
                throw new ONSClientException("MQMessage failed" , e);
            }
        });
        producer = ONSFactory.createProducer(properties);
        producer.start();
        logger.info("The aliyun message queue producer starts successfully.");
    }

    private static class SingletonHolder {
        private static final ProducerServer INSTANCE = new ProducerServer();
    }

    public static ProducerServer getInstance(final ProducerProperties properties , final MqBaseProperties baseProperties){
        producerProperties = properties;
        mqBaseProperties = baseProperties;
        // 检测必须的参数
        if (StringUtils.isEmpty(properties.getAccessKey())) {
            throw new ONSClientException("please set access key");
        }

        if (StringUtils.isEmpty(properties.getSecretKey())) {
            throw new ONSClientException("please set secret key");
        }

        return SingletonHolder.INSTANCE;
    }

    public boolean send(Message message)  {
        logger.info("Start sending messages.");

        if(message == null || message.getBody() == null ){
            logger.error("不能发送空消息!");
            return false;
        }

        //全局默认tag
        if(StringUtils.isEmpty(message.getTag())){
            message.setTag(mqBaseProperties.getTag());
        }

        //全局默认topic
        if(StringUtils.isEmpty(message.getTopic())){
            message.setTopic(mqBaseProperties.getTopic());
        }

        com.aliyun.openservices.ons.api.Message aliMessage = new com.aliyun.openservices.ons.api.Message();
        aliMessage.setTopic(message.getTopic());
        aliMessage.setTag(message.getTag());
        if(message.getDelayTime() != null) {
            aliMessage.setStartDeliverTime(System.currentTimeMillis() + message.getDelayTime() * 1000);
        }

        SendResult result = null ;
        try {
            aliMessage.setBody(SerializationUtils.serialize(message.getBody()));
            result = producer.send(aliMessage);
        }catch (ONSClientException e){
            logger.error("MQMessage failed:" + e.getMessage());
            throw new ONSClientException("MQMessage failed");
        } catch (IOException e) {
            logger.error("MQMessage failed:" + e.getMessage());
            throw new ONSClientException(e);
        }
        logger.info("End of message.");
        return result != null;
    }

    public void shutdown(){
        logger.info("The aliyun message queue producer is destroyed.");
        producer.shutdown();
    }

}
